/*
 * @Author: LVGRAPE
 * @Date: 2023-09-08 17:56:24
 * @LastEditTime: 2023-10-18 16:29:47
 * @LastEditors: LVGRAPE
 * @Description:
 * @FilePath: \rt_ZINO_RC_PRO\ZINO\rc\rc.c
 * 要啥没啥，爱咋咋的
 */

#include "drv_common.h"
#include "si24r1.h"
#include <rtconfig.h>
#include <rtthread.h>
#include "rc.h"
#include "zino_config.h"
#include "zino.h"
#include "maths.h"
#define DBG_TAG "2.4G"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>


#define CRC_MAGICBEE 0XED
#define SI24R1_SPI_DEV_NAME         "spi_nrf"
#define SI24R1_CE_PIN               GET_PIN(C,11)
#define SI24R1_IRQ_PIN              GET_PIN(D,2)

ZINO_CONFIG_DECLARE(struct rc_config, rc_config);
ZINO_CONFIG_REGISTER(struct rc_config, rc_config, 2, 1);

const static char* ROLE_TABLE[] = { "PTX", "PRX" };
static struct rc_handle rchandle =
{
    .pair_addr = "UAVI1",
    .pair_channel = 33,
    .pair_fc_handshake_byte = 0xfc,
    .pair_rc_handshake_byte = 0x9c,
    .pair_handshake_byte = 0x0A,
    .pair_handshake_byte_v1 = 0x1A,
    .pair_sync_time = 1500,
    .pair_wait_time = 10000,
};
/**
 * @brief 接收完成处理函数
 *
 * @param nrf24
 * @param data
 * @param len
 * @param pipe
 */
static void rx_ind(struct si24r1* s, uint8_t* data, uint8_t len, int pipe)
{
    /*! Don't need to care the pipe if the role is ROLE_PTX */
    rt_kprintf("(p%d)_%d: ", pipe,len);
    uint8_t crc = crc8_dvb_s2_update(CRC_MAGICBEE, data, len - 1);
    if (crc == data[len - 1])
    {
        // LOG_D("Crc ok!");
        rchandle.rxCnt++;
        rt_memcpy(rchandle.rx_msg.raw, data, len);
        LOG_D("RC: %d \t %d \t %d \t %d \t %d \t %d \t %d \t %d \t %dHz \t",
        rchandle.rx_msg.v.channel[0],
        rchandle.rx_msg.v.channel[1],
        rchandle.rx_msg.v.channel[2],
        rchandle.rx_msg.v.channel[3],
        rchandle.rx_msg.v.channel[4],
        rchandle.rx_msg.v.channel[5],
        rchandle.rx_msg.v.channel[6],
        rchandle.rx_msg.v.channel[7],
        rchandle.rx_rssi
        );
    }
    // si24r1_send_data(s, rchandle.tx_msg.raw, RTX_BUFFER_SIZE, pipe);
    // else
    // {
    //     LOG_D("Crc error! c%02X != r%02X",crc,data[len-1]);
    // }
    // for(uint8_t i = 0; i < len; i++)
    // {
    //     rt_kprintf("0x%02X ",data[i]);
    // }
    // rt_kprintf("Rcnt:%d ",rchandle.rx_rssi);
    // rt_kprintf("\n");
    // rt_timer_stop(rchandle.timeout);
}
/**
 * @brief 发送完成处理函数
 *
 * @param nrf24
 * @param pipe
 */
static void tx_done(struct si24r1* s, int pipe)
{
    static int cnt = 0;
    static char tbuf[32];

    cnt++;

    /*! Here just want to tell the user when the role is ROLE_PTX
    the pipe have no special meaning except indicating (send) FAILED or OK
        However, it will matter when the role is ROLE_PRX*/
    if (s->user_config.role == SI24R1_ROLE_TX)
    {
        if (pipe == 8)
            rt_kprintf("tx_done failed");
        else
            rt_kprintf("tx_done ok");
    }
    else
    {
        rt_kprintf("tx_done ok");
    }

    rt_kprintf(" (pipe%d)\n", pipe);

    rt_sprintf(tbuf, "My role is %s [%dth]\n", ROLE_TABLE[s->user_config.role], cnt);
    // si24r1_send_data(s, (uint8_t*)tbuf, rt_strlen(tbuf), pipe);
#ifdef PKG_NRF24L01_DEMO_ROLE_PTX
    rt_thread_mdelay(NRF24_DEMO_SEND_INTERVAL);
#endif
}

static struct si24r1_callback si24r1_cb = {
    .rx_ind = rx_ind,
    .tx_done = tx_done,
};
/**
 * @brief 摇控器si24r1的配置，
 * 信号丢失时，参数变化时，需要调用一下来更新si24r1的寄存器配置
 *
 * @param rc
 */
void rc_si24r1_setting(struct rc_handle* rc)
{
    rt_memcpy(rc->address, "test3", 5);
    rc->rf_channel = 125;

    rt_memset(&rc->si24r1.onchip_config, 0, sizeof(rc->si24r1.onchip_config));
    rt_memcpy(rc->si24r1.onchip_config.rx_addr_p0.addr, rc->address, 5);
    rt_memcpy(rc->si24r1.onchip_config.tx_addr.addr, rc->address, 5);
    rc->si24r1.onchip_config.en_rxaddr.ERX_P0 = 1;
    rc->si24r1.onchip_config.rf_ch.RF_CH = rc->rf_channel;
    rc->si24r1.onchip_config.rx_pw_p0.RX_PW_P0 = RTX_BUFFER_SIZE;
    rc->si24r1.onchip_config.setup_aw.AW = 0x03;
    rc->si24r1.onchip_config.feature.EN_DPL = 1;
    rc->si24r1.onchip_config.rf_setup.RF_DR_HIGH = 1;
    rc->si24r1.onchip_config.rf_setup.RF_PWR = 6;
    rc->si24r1.onchip_config.config.EN_CRC = 1;
    rc->si24r1.onchip_config.config.CRCO = 1;
    rc->si24r1.onchip_config.config.PWR_UP = 1;
    rc->si24r1.onchip_config.config.PRIM_RX = 1;
    rc->si24r1.onchip_config.dynpd.DPL_P0 = 1;

    rc->si24r1.onchip_config.status.MAX_RT=1;//清除中断
    rc->si24r1.onchip_config.status.RX_DR=1;//清除中断
    rc->si24r1.onchip_config.status.TX_DS=1;//清除中断
    rc->si24r1.onchip_config.en_aa.ENAA_P0 = 1;

    rc->si24r1.user_config.role = SI24R1_ROLE_RX;

    si24r1_update_onchip_config(&rc->si24r1);
    // si24r1_check_all_reg(&rc->si24r1);
}
#define PKG_SI24R1_VERSION "v1.0.0"
static void si24r1_thread(void* param)
{
    rt_err_t ret = RT_EOK;
    struct si24r1 *si= (struct si24r1 *)param;
    LOG_I("2.4G wireless handle:%s\n", PKG_SI24R1_VERSION);
    do {
        ret = si24r1_init(si, SI24R1_SPI_DEV_NAME, SI24R1_CE_PIN, SI24R1_IRQ_PIN, &si24r1_cb);
        if (ret != RT_EOK)
        {
            LOG_E("Failed to init si24r1. Next try in 3 second.");
            rt_thread_mdelay(3000);
        }
    } while (ret != RT_EOK);
    LOG_I("si24r1_thread running...");
    // rchandle.si24r1.flags.using_irq = 1;
    while (1)
    {
        si24r1_run(si);
        if (si->flags.using_irq)
            rt_thread_mdelay(10);
    }
    // return 0;
}
void rc_set_pairing_mode(struct rc_handle* rc)
{
    if (rchandle.mode != RC_MODE_PAIRING)
    {
        rchandle.mode = RC_MODE_PAIRING;
        rchandle.si24r1.onchip_config.config.PRIM_RX = 0;
    }
}
static void rc_second_timer_cb(void* parameter)
{
    struct rc_handle* rc = (struct rc_handle*)parameter;
    static uint8_t lostCnt=0;
    rc->rx_rssi = rc->rxCnt;
    rc->rxCnt = 0;

    if (rc->rx_rssi == 0)
    {
        if(lostCnt ++ == 3)
        {
            lostCnt = 0;
            rt_event_send(rc->event, RC_EVENT_LOST);
        }
    }
}
static void rc_thread(void* param)
{
    struct rc_handle* rc = (struct rc_handle*)param;
    rc->event = rt_event_create("rc_event", RT_IPC_FLAG_FIFO);
    rc->second_timer = rt_timer_create("rc_1s", rc_second_timer_cb, rc, 1000, RT_TIMER_FLAG_PERIODIC);
    rt_timer_start(rc->second_timer);
    while (1)
    {
        uint32_t event=0;
        if(rt_event_recv(rc->event, RC_EVENT_ALL, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &event) == RT_EOK)
        {
            LOG_D("rc_event: 0x%08X", event);
            switch (event)
            {
            case RC_EVENT_LOST:
                LOG_D("RC_EVENT_LOST");
                rc_si24r1_setting(rc);
                // rt_sem_release(rc->si24r1.sem);
                break;
            
            default:
                break;
            }
        }
    }
}
static int rc_task_init(void)
{
    struct rc_handle* rc = &rchandle;
    rt_thread_t thread1,thread2;
    thread1 = rt_thread_create("2.4G wl", si24r1_thread, &rc->si24r1, 1024, RT_THREAD_PRIORITY_MAX / 2, 20);
    thread2 = rt_thread_create("rc task", rc_thread, rc, 1024, RT_THREAD_PRIORITY_MAX / 2, 20);
    rt_thread_startup(thread1);
    rt_thread_startup(thread2);

    return RT_EOK;
}
void rc_set(int arg_c, char** arg_v)
{
    rchandle.rf_channel = atoi(arg_v[1]);
    LOG_D("set rf channel:%d", rchandle.rf_channel);
    rc_si24r1_setting(&rchandle);
    si24r1_check_all_reg(&rchandle.si24r1);
}
MSH_CMD_EXPORT(rc_set, set rc);
ZINO_APP_EXPORT(rc_task_init);
